home *** CD-ROM | disk | FTP | other *** search
/ The Atari Compendium / The Atari Compendium (Toad Computers) (1994).iso / files / prgtools / mint / mgr / sparcmgr / src.zoo / src / put_window.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-03-17  |  44.0 KB  |  1,290 lines

  1. /*                        Copyright (c) 1987 Bellcore
  2.  *                            All Rights Reserved
  3.  *       Permission is granted to copy or use this program, EXCEPT that it
  4.  *       may not be sold for profit, the copyright notice must be reproduced
  5.  *       on copies, and credit should be given to Bellcore where it is due.
  6.  *       BELLCORE MAKES NO WARRANTY AND ACCEPTS NO LIABILITY FOR THIS PROGRAM.
  7.  */
  8. /*    $Header: put_window.c,v 1.2 89/03/17 09:39:00 sau Exp $
  9.     $Source: /m1/mgr.new/src/RCS/put_window.c,v $
  10. */
  11. static char    RCSid_[] = "$Source: /m1/mgr.new/src/RCS/put_window.c,v $$Revision: 1.2 $";
  12.  
  13. /* Very simple terminal emulator (this is an old comment) */
  14.  
  15. #include <sys/time.h>        /* experimental */
  16. #include "bitmap.h"
  17. #include "font.h"
  18. #include "defs.h"
  19. #include "menu.h"
  20. #include "event.h"
  21. #include <stdio.h>
  22. #include "window.h"
  23. #include "clip.h"
  24.  
  25. /* macros for putting a character on a window */
  26.  
  27. #define DO_CHAR(font,c) \
  28.     ((font)->glyph[c])
  29.     
  30. #ifdef COLOR
  31. #define PUT_CHAR(dest,x,y,font,op,c)   \
  32.    bit_blit(dest,x,y-fsizehigh,fsizewide,fsizehigh, \
  33.    BIT_SRC | (W(background)&~NOCOLOR),BIT_NULL,0,0), \
  34.    bit_blit(dest,x,y-fsizehigh,fsizewide,fsizehigh, \
  35.    (op & NOCOLOR)^BIT_DST | (op ^ W(background))&~NOCOLOR, \
  36.    DO_CHAR(font,c),0,0)
  37.  
  38. /* fix the border color */
  39.  
  40. #define BORDER(win) \
  41.    ((win==active) ? border(win,SUM_BDR-1,1) : border(win,BLK_BDR,WH_BDR))
  42.  
  43. #else NOCOLOR
  44.  
  45. #define PUT_CHAR(dest,x,y,font,op,c)    \
  46.     bit_blit(dest,x,y-fsizehigh,fsizewide,fsizehigh, \
  47.     op,DO_CHAR(font,c),0,0)
  48. #define BORDER(win)
  49.  
  50. #endif
  51. #define Abs(x)               ((x)>0?(x):-(x))
  52.  
  53. /* flseep is experimental */
  54.  
  55. #define fsleep() \
  56.    { \
  57.    struct timeval time; \
  58.    time.tv_sec = 0; \
  59.    time.tv_usec = 330000; \
  60.    select(0,0,0,0,&time); \
  61.    }
  62.  
  63. rect clip;                /* clipping rectangle */
  64.  
  65. /* send a string to a window, interpret ESC's
  66.  * return # of chars actually processed
  67.  */
  68.  
  69. int
  70. put_window(win,buff,buff_count)
  71. register WINDOW *win;                    /* window to update */
  72. register char *buff;                    /* ptr to update text */
  73. int buff_count;                        /* # of characters */
  74.    {
  75.    register BITMAP *window;            /* bitmap to update */
  76.    register BITMAP *text = (BITMAP *) 0;    /* current text region */
  77.    register int indx;                /* index into buff */
  78.    register int cnt;                /* # of esc. numbers */
  79.    register char c;                /* current char */
  80.    register int done=0;                /* set to 1 to exit */
  81.    int bell=0;                    /* 1 if screen flashed once */
  82.    int sub_window = 0;                /* sub window created */
  83.    int fsizehigh, fsizewide;            /* variables to save deref. */
  84.    struct font *Get_font();    
  85.    char *malloc(), *binary();
  86.    struct menu_state *do_menu();
  87.    char *trans();
  88.  
  89.    /* set up environment */
  90.  
  91.    if (W(flags)&W_ACTIVE) {
  92.       window = W(window);
  93.       }
  94.    else {
  95.       window = bit_create(W(save),SUM_BDR,SUM_BDR,
  96.                           BIT_WIDE(W(window)),BIT_HIGH(W(window)));
  97.       sub_window++;
  98.       }
  99.  
  100.    if (window==(BITMAP *) 0) {        /* never! */
  101.       perror("Bit_create failed for window");
  102.       return(0);
  103.       }
  104.  
  105.    /* avoid repeated dereferencing of pointers */
  106.  
  107.    fsizehigh = FSIZE(high);
  108.    fsizewide = FSIZE(wide);
  109.  
  110.    if (Do_clip()) {
  111.       Set_clipall();
  112.       Set_cliplow(W(x)+W(text).x,W(y)+W(text).y-fsizehigh);
  113.       }
  114.  
  115.    if (W(text.wide))
  116.       text = bit_create(window,W(text.x),W(text.y),W(text.wide),W(text.high)); 
  117.    if (text == (BITMAP *) 0)
  118.       text = window;
  119.  
  120.    if (W(flags)&W_ACTIVE && mousein(mousex,mousey,win,0)) {
  121.       MOUSE_OFF(mousex,mousey);
  122.       }
  123.  
  124.    if (win==active)
  125.       cursor_off();
  126.  
  127.    /* do each character */
  128.  
  129.    for(indx=0;c= *buff++, indx<buff_count && !done; indx++)
  130.    switch (W(flags)&W_STATE) {
  131.  
  132.       /* download and process text strings */
  133.  
  134.    case W_TEXT:                /* down load a text string */
  135.       cnt = W(esc_cnt);
  136.          W(snarf[W(esc)[TEXT_COUNT]++]) = c;
  137.       if (W(esc)[TEXT_COUNT] >= W(esc)[cnt]) {
  138.          W(snarf)[W(esc)[TEXT_COUNT]] = '\0';
  139.          W(flags) &= ~W_TEXT;
  140.          if (W(snarf) && W(code)!=T_BITMAP && W(code)!=T_GRUNCH)
  141.             (void) trans(W(snarf));
  142.          down_load(win,window,text);
  143.          done++;
  144.          }
  145.       break;
  146.  
  147.    /**********************************************************************
  148.     *    Handle escape codes 
  149.     */
  150.  
  151.    case W_ESCAPE:            /* process an escape code */
  152.       W(flags) &= ~(W_ESCAPE);
  153.       cnt = W(esc_cnt);
  154.       switch(c&=0177) {
  155.          case ESC :             /* turn on escape mode */
  156.                     W(flags) |= W_ESCAPE;
  157.                     W(esc_cnt) = 0;
  158.                     W(esc[0]) = 0;
  159.                     break;
  160.  
  161.          case '0': case '1': case '2': case '3': case '4':
  162.          case '5': case '6': case '7': case '8': case '9':
  163.                W(esc)[W(esc_cnt)] = W(esc)[W(esc_cnt)]*10 + c-'0'; 
  164.                W(flags) |= W_ESCAPE;
  165.                if (W(flags)&W_MINUS && W(esc)[W(esc_cnt)] > 0) {
  166.                   W(esc)[W(esc_cnt)] = -(W(esc)[W(esc_cnt)]);
  167.                   W(flags) &= ~(W_MINUS);
  168.                   }
  169.                break;
  170.  
  171.          case E_SEP1:            /* primary field separator */
  172.          case E_SEP2:            /* secondary field separator */
  173.                if (W(esc_cnt)+1 < MAXESC)
  174.                    W(esc_cnt)++;
  175.                W(esc)[W(esc_cnt)] = 0;
  176.                W(flags) &= ~(W_MINUS);
  177.                W(flags) |= W_ESCAPE;
  178.                break;
  179.  
  180.          case E_MINUS:          /* set the MINUS flag */
  181.                W(flags) |= (W_ESCAPE|W_MINUS);
  182.                break;
  183.  
  184.          case E_NULL:            /* do nothing */
  185.                done++;
  186.                break;
  187.  
  188.          case E_ADDLINE:          /* add a new line */
  189.                if (*W(esc)) {
  190.                   register int count = *W(esc);
  191.                   scroll(win,text,W(y)-fsizehigh,T_HIGH,- count*(fsizehigh),
  192.                       W(background));
  193.                   }
  194.                else {
  195.                   scroll(win,text,W(y)-fsizehigh,T_HIGH,-(fsizehigh),
  196.                       W(background));
  197.                   bit_blit(text,0,HIGH-fsizehigh,T_WIDE,
  198.                       fsizehigh,W(background),NULL_DATA,0,0);
  199.                   }
  200.                done++;
  201.                break;
  202.  
  203.          case E_ADDCHAR:          /* insert a character */
  204.                {
  205.                register int wide = (fsizewide) * (*W(esc) ? *W(esc) : 1);
  206.                if (wide+W(x)>T_WIDE)
  207.                   wide = T_WIDE-W(x);
  208.                bit_blit(text,W(x)+wide,W(y)-fsizehigh,
  209.                         T_WIDE-W(x)-wide, fsizehigh,BIT_SRC,
  210.                         text,W(x),W(y)-fsizehigh);
  211.                bit_blit(text,W(x),W(y)-fsizehigh,wide,
  212.                     fsizehigh,W(background),0,0,0);
  213.                }
  214.                break;
  215.  
  216.          case E_DELETELINE:          /* delete a line */
  217.                if (*W(esc)) {
  218.                   register int count = *W(esc);
  219.                   scroll(win,text,W(y)-fsizehigh,T_HIGH,count*fsizehigh,
  220.                       W(background));
  221.                   }
  222.                else {
  223.                   scroll(win,text,W(y)-fsizehigh,T_HIGH,fsizehigh,
  224.                       W(background));
  225.                   }
  226.                done++;
  227.                break;
  228.  
  229.          case E_DELETECHAR:          /* delete a character */
  230.                {
  231.                register int wide = (fsizewide) * (*W(esc) ? *W(esc) : 1);
  232.                if (wide+W(x)>T_WIDE)
  233.                   wide = T_WIDE-W(x);
  234.                bit_blit(text,W(x),W(y)-fsizehigh,
  235.                         T_WIDE-W(x)-wide, fsizehigh,BIT_SRC,
  236.                         text,W(x)+wide,W(y)-fsizehigh);
  237.                bit_blit(text,T_WIDE-wide,W(y)-fsizehigh,wide,
  238.                     fsizehigh,W(background),0,0,0);
  239.                }
  240.                break;
  241.  
  242.          case E_UPLINE:          /* up 1 line */
  243. #ifdef FRACCHAR
  244.                if (cnt>0) {    /* move up fractions of a character line */
  245.                   int div = W(esc)[1] == 0 ? 1 : W(esc)[1];
  246.                   int n = W(esc)[0] * fsizehigh / div;
  247.                   if (W(y)>n) {
  248.                      W(y) -= n;
  249.                      if (Do_clip())
  250.                         Set_cliplow(10000,W(y)+W(text).y-fsizehigh);
  251.                      }
  252.                   break;
  253.                   }
  254. #endif
  255.                if (W(y)>fsizehigh) W(y) -= fsizehigh;
  256.                if (Do_clip())
  257.                   Set_cliplow(10000,W(y)+W(text).y-fsizehigh);
  258.                break;
  259.  
  260.          case E_RIGHT:          /* right 1 line */
  261. #ifdef FRACCHAR                
  262.                if (cnt>0) {    /* move right/left a fraction of a character */
  263.                   int div = W(esc)[1] == 0 ? 1 : W(esc)[1];
  264.                   int n = W(esc)[0] * fsizewide / div;
  265.                   W(x) += n;
  266.                   if (W(x) < 0)
  267.                      W(x) = 0;
  268.                   break;
  269.                   }
  270. #endif
  271.                W(x) += fsizewide;
  272.                break;
  273.  
  274.          case E_DOWN:            /* down 1 line */
  275. #ifdef FRACCHAR
  276.                if (cnt>0) {    /* move down a fraction of a character */
  277.                   int div = W(esc)[1] == 0 ? 1 : W(esc)[1];
  278.                   int n = W(esc)[0] * fsizehigh / div;
  279.                         if (W(y)+n > T_HIGH) {
  280.                             scroll(win,text,0,T_HIGH,n,W(background));
  281.                             done++;
  282.                             }
  283.                   else {
  284.                             W(y) += n;
  285.                             if (Do_clip())
  286.                                 Set_cliphigh(0,W(y)+W(text).y);
  287.                      }
  288.                   break;
  289.                   }
  290. #endif
  291.                if (W(y)+fsizehigh > T_HIGH) {
  292.                   scroll(win,text,0,T_HIGH,fsizehigh,W(background));
  293.                   done++;
  294.                   }
  295.                else {
  296.                   W(y) += fsizehigh;
  297.                   if (Do_clip())
  298.                      Set_cliphigh(0,W(y)+W(text).y);
  299.                   }
  300.                break;
  301.  
  302.          case E_FCOLOR:       /* set forground color */
  303.                W(style) = (W(style)&NOCOLOR) | GETCOLOR(*W(esc));
  304.                BORDER(win);
  305.                break;
  306.  
  307.          case E_BCOLOR:       /* set background color */
  308.                W(background) = (W(background)&NOCOLOR) | GETCOLOR(*W(esc));
  309.                BORDER(win);
  310.                break;
  311.  
  312.          case E_STANDOUT:        /* inverse video (characters) */
  313.            standout( win );
  314.                break;
  315.  
  316.          case E_STANDEND:        /* normal video (characters) */
  317.            standend( win );
  318.                break;
  319.  
  320.          case E_CLEAREOL:          /* clear to end of line */
  321.                bit_blit(text,W(x),W(y)-fsizehigh,T_WIDE-W(x),
  322.                     fsizehigh,W(background),0,0,0);
  323.                if (Do_clip())
  324.                   Set_cliphigh(BIT_WIDE(W(window)),0);
  325.                break;
  326.  
  327.          case E_CLEAREOS:          /* clear to end of window */
  328.                bit_blit(text,W(x),W(y)-fsizehigh,T_WIDE-W(x),
  329.                     fsizehigh,W(background),0,0,0);
  330.                bit_blit(text,0,W(y),T_WIDE,T_HIGH-W(y),W(background),0,0,0);
  331.                if (Do_clip())
  332.                   Set_cliphigh(BIT_WIDE(W(window)),BIT_HIGH(window));
  333.                break;
  334.  
  335.          case E_SETCURSOR:            /* set the character cursor */
  336.                     W(curs_type) = *W(esc);
  337.                     break;
  338.          case E_BLEEP:            /* highlight a section of the screen */
  339.                if (cnt>2) {
  340.                   register int *p = W(esc);
  341.                   if (p[0]<0 || p[1]<0 )
  342.                      break;
  343.                   p[2] = BETWEEN(1,p[2],BIT_WIDE(screen)-1);
  344.                   p[3] = BETWEEN(1,p[3],BIT_WIDE(screen)-1);
  345.                   bit_blit(screen,p[0],p[1],p[2],p[3],BIT_NOT(BIT_DST),NULL_DATA,0,0);
  346.                   fsleep();
  347.                   bit_blit(screen,p[0],p[1],p[2],p[3],BIT_NOT(BIT_DST),NULL_DATA,0,0);
  348.                   done++;
  349.                   }
  350.                break;
  351.  
  352.          case E_FONT:              /* pick a new font */
  353. #ifdef CUT
  354.                W(flags) &= ~W_SNARFABLE;
  355. #endif
  356.                if (cnt > 0) {
  357.                   W(esc)[TEXT_COUNT] = 0;
  358.                   if (W(esc)[cnt]>0 && (W(snarf)=malloc(W(esc)[cnt]+1)) != (char *)0)
  359.                      W(flags) |= W_TEXT;
  360.                   W(code) = T_FONT;
  361.                   break;
  362.                   }
  363.  
  364.                   {
  365.                   int font_count = W(esc)[cnt];
  366.                   int baseline = FSIZE(baseline);
  367.  
  368.                   W(font)=Get_font(font_count);
  369.           fsizehigh = FSIZE(high);
  370.           fsizewide = FSIZE(wide);
  371.                   W(y) += FSIZE(baseline)-baseline;
  372.                   if (W(y) < fsizehigh) {
  373.                      scroll(win,text,W(y)-fsizehigh,T_HIGH,
  374.                             W(y)-fsizehigh,W(background));
  375.                      W(y)=fsizehigh;
  376.                      done++;
  377.                      }
  378.                   }
  379.                break;
  380.  
  381.          case E_MOUSE:          /* testing  -- move the mouse */
  382.                MOUSE_OFF(mousex,mousey);
  383.                if (W(esc_cnt) < 1) {
  384.                   mousex = W(x0) + W(x);
  385.                   mousey = W(y0) + W(y);
  386.                   }
  387.                else {
  388.                   mousex = W(esc)[cnt-1];
  389.                   mousey = W(esc)[cnt];
  390.                   mousex = BETWEEN(0,mousex,BIT_WIDE(screen)-1);
  391.                   mousey = BETWEEN(0,mousey,BIT_HIGH(screen)-1);
  392.                   }
  393.                if (!(W(flags)&W_ACTIVE && mousein(mousex,mousey,win,0)))
  394.                   MOUSE_ON(mousex,mousey);
  395.                break;
  396.  
  397.          case E_SIZE:              /* reshape window: cols, rows */
  398.                if (!W(flags)&W_ACTIVE) break;
  399.                if (cnt >= 1) {
  400.                   int cols = W(esc)[cnt-1];
  401.                   int lines = W(esc)[cnt];
  402.                   int x = W(x0), y = W(y0);
  403.  
  404.                   MOUSE_OFF(mousex,mousey);
  405.  
  406.                   if (cnt>=3) {
  407.                      x = W(esc)[0];
  408.                      y = W(esc)[1];
  409.                      }
  410.  
  411.                   if (win!=active)
  412.                      cursor_off();
  413.                   ACTIVE_OFF();
  414.                   expose(win);
  415.                   shape(x, y,
  416.                         cols?cols*fsizewide+2*SUM_BDR:
  417.                              2*SUM_BDR + WIDE,
  418.                         lines?lines*fsizehigh+2*SUM_BDR:
  419.                              2*SUM_BDR + HIGH);
  420.                   ACTIVE_ON();
  421.                   if (!(W(flags)&W_ACTIVE && mousein(mousex,mousey,win,0)))
  422.                      MOUSE_ON(mousex,mousey);
  423.                   done++;
  424.                   }
  425.                break;
  426.  
  427.          case E_PUTSNARF:          /* put the snarf buffer */
  428.                if (snarf)
  429.                   Write(W(to_fd),snarf,strlen(snarf));
  430. #ifdef DEBUG
  431.                dprintf(y)(stderr,"%s: sending yank buffer [%s]\n",W(tty),
  432.                          snarf?snarf:"EMPTY");
  433. #endif
  434.                break;
  435.  
  436.          case E_GIMME:          /* snarf text into input queue */
  437.                W(esc)[TEXT_COUNT] = 0;
  438.                if (W(esc)[cnt]>0 && W(esc)[cnt]<MAXSHELL &&
  439.                           (W(snarf)=malloc(W(esc)[cnt]+1)) != (char *)0)
  440.                   W(flags) |= W_TEXT;
  441.                W(code) = T_GIMME;
  442.                break;
  443.  
  444.          case E_GMAP:          /* read a bitmap from a file */
  445. #ifdef DEBUG
  446.               dprintf(*)(stderr,"%s: fetching bitmap %d\r\n",
  447.                                W(tty),*W(esc)-1);
  448. #endif
  449.                W(esc)[TEXT_COUNT] = 0;
  450.                if (W(esc)[cnt]>0 && W(esc)[cnt]<MAX_PATH &&
  451.                           (W(snarf)=malloc(W(esc)[cnt]+1)) != (char *)0)
  452.                   W(flags) |= W_TEXT;
  453.                W(code) = T_GMAP;
  454.                break;
  455.  
  456.          case E_SMAP:          /* save a bitmap on a file */
  457.                W(esc)[TEXT_COUNT] = 0;
  458.                if (W(esc)[cnt]>0 && W(esc)[cnt]<MAX_PATH &&
  459.                           (W(snarf)=malloc(W(esc)[cnt]+1)) != (char *)0) {
  460.                   W(flags) |= W_TEXT;
  461. #ifdef DEBUG
  462.                   dprintf(*)(stderr,"%s: saving bitmap %d\r\n",
  463.                                W(tty),*W(esc)-1);
  464. #endif
  465.                   }
  466.                W(code) = T_SMAP;
  467.                break;
  468.  
  469.          case E_SNARF:          /* snarf text into the snarf buffer */
  470.                W(esc)[TEXT_COUNT] = 0;
  471.                if (W(esc)[cnt]>=0 &&    /*** was just > */
  472.                           (W(snarf)=malloc(W(esc)[cnt]+1)) != (char *)0)
  473.                   W(flags) |= W_TEXT;
  474.                W(code) = T_YANK;
  475.                break;
  476.  
  477.          case E_STRING:          /* write text into the offscreen bitmap */
  478.                W(esc)[TEXT_COUNT] = 0;
  479.                if (W(esc)[cnt]>0 && /* W(bitmaps)[*W(esc)-1] && */
  480.                           (W(snarf)=malloc(W(esc)[cnt]+1)) != (char *)0)
  481.                   W(flags) |= W_TEXT;
  482.                W(code) = T_STRING;
  483.                break;
  484.  
  485.          case E_GRUNCH:          /* graphics scrunch mode  (experimental) */
  486.                W(esc)[TEXT_COUNT] = 0;
  487.                if (W(esc)[cnt]>=0 &&    /*** was just > */
  488.                           (W(snarf)=malloc(W(esc)[cnt]+1)) != (char *)0)
  489.                   W(flags) |= W_TEXT;
  490.                W(code) = T_GRUNCH;
  491.                break;
  492.  
  493. #ifdef XMENU
  494.          case E_XMENU:              /* extended menu stuff */
  495.                                         /* ^[3X    remove menu 3 from window */
  496.                                         /* ^[3,4X    select item 4 of menu 3 */
  497.                                         /* ^[1,2,3X    display menu 3 at 1,2 */
  498.                                         /* ^[1,2,3,4Xhighlight menu 3 item 4 at 1,2 */
  499.                {
  500.                register int *p = W(esc);
  501.                register struct menu_state *menu;
  502.                switch(cnt) {
  503.                   case 0:            /* remove menu from display */
  504.                      if (p[0]>=0 && p[0]<MAXMENU && (menu=W(menus[p[0]])))
  505.                         menu_remove(menu);
  506.                   case 1:            /* select active item */
  507.                      if (p[0]>=0 && p[0]<MAXMENU && (menu=W(menus[p[0]])))
  508.                         menu->current = p[1];
  509.                      break;
  510.                   case 2:            /* display menu  on window */
  511.                      if (p[2]>=0 && p[2]<MAXMENU && (menu=W(menus[p[2]])))
  512.                         menu_setup(menu,window,Scalex(p[0]),Scaley(p[1]),-1);
  513.                      break;
  514.                   case 3:            /* highlight menu item on window */
  515.                      if (p[2]>=0 && p[2]<MAXMENU && 
  516.                                    (menu=W(menus[p[2]])) && menu->menu) {
  517.                         bit_blit(window, Scalex(p[0])+MENU_BORDER,
  518.                                  Scaley(p[1])+(p[3]-1)*menu->bar_sizey+
  519.                                  MENU_BORDER,
  520.                                menu->bar_sizex, menu->bar_sizey,
  521.                                BIT_NOT(BIT_DST), NULL_DATA, 0, 0);
  522.                         }
  523.                      break;
  524.                      }
  525.                }
  526.                break;
  527. #endif
  528.          case E_MENU:              /* get a menu */
  529.                {            /* should be split into several cases */
  530.                register int b = (W(esc)[0]<0);        /* which button */
  531.                register int n = Abs(W(esc)[0]);        /* menu number */
  532.  
  533.                /* setup menu pointer */
  534.  
  535.                if (cnt > 2) {
  536.                   int parent = n;        /* parent menu # */
  537.                   int child = W(esc[2]);    /* child menu number */
  538.                   int item = W(esc[1]);        /* item # of parent */
  539.                   int flags = W(esc[3]);    /* menu flags */
  540.  
  541.                   if (parent<0 || parent >= MAXMENU || child >= MAXMENU ||
  542.                       W(menus[parent])==(struct menu_state*)0)
  543.                      break;
  544.  
  545. #ifdef DEBUG
  546.                   dprintf(M)(stderr,"Linking menu %d to parent %d at item %d\n",
  547.                              child,parent,item);
  548. #endif
  549.  
  550.                   if (item<0)                    /* page link */
  551.                      W(menus[parent])->next = child;
  552.                   else if (item < W(menus[parent])->count)    /* slide lnk */
  553.                      menu_setnext(W(menus[parent]),item) = child; 
  554.  
  555.                   /* menu flags */
  556.  
  557.                   if (flags > 0)
  558.                      W(menus[parent])->flags = flags;
  559.  
  560.                   break;
  561.                   }
  562.  
  563.                /* download a menu */
  564.  
  565.                if (cnt > 0) {
  566.                   W(esc)[TEXT_COUNT] = 0;
  567.                   if (W(menus)[n]) {
  568.                      menu_destroy(W(menus)[n]);
  569.                      W(menus)[n] = (struct menu_state *) 0;
  570.                      if (W(menu[0])== n)
  571.                         W(menu[0]) = -1;
  572.                      if (W(menu[1])== n)
  573.                         W(menu[1]) = -1;
  574.                      }
  575.                   if (W(esc)[cnt]>0 && (W(snarf)=malloc(W(esc)[cnt]+1))
  576.                                      != (char *)0) {
  577.                      W(flags) |= W_TEXT;
  578.                      W(code) = T_MENU;
  579.                      }
  580. #ifdef DEBUG
  581.                   dprintf(M)(stderr,"downloading menu %d\n",n);
  582. #endif
  583.                   }
  584.  
  585.                /* select menu number */
  586.  
  587.                else if (n < MAXMENU && W(menus)[n]) {
  588.                   int last_menu = W(menu[b]);  
  589.  
  590. #ifdef DEBUG
  591.                   dprintf(M)(stderr,"selecting menu %d on button %d\n",n,b);
  592. #endif
  593.                   W(menu[b]) = n;
  594.                   if (last_menu<0 && button_state==(b?BUTTON_1:BUTTON_2))
  595.                      go_menu(b);
  596.                   }
  597.                else
  598.                   W(menu[b]) = -1;
  599.                }
  600.                break;
  601.  
  602.          case E_EVENT:            /* get an event */
  603.                switch(cnt) {
  604.                   case 2:    /* append to an event */
  605.                   case 1:    /* set an event */
  606.                      W(esc)[TEXT_COUNT] = 0;
  607.                      if (W(esc)[cnt]>0 && (W(snarf)=malloc(W(esc)[cnt]+1))
  608.                                   != (char *)0) {
  609.                         W(flags) |= W_TEXT;
  610.                         W(code) = T_EVENT;
  611.                         }
  612.                      break;
  613.                   case 0:
  614.                     cnt = W(esc)[0];
  615.             if( !CHK_EVENT(cnt) )
  616.                break;
  617.                     EVENT_CLEAR_MASK(win,cnt);
  618.                     if (W(events)[GET_EVENT(cnt)]) {
  619.                        free (W(events)[GET_EVENT(cnt)]);
  620.                        W(events)[GET_EVENT(cnt)] = (char *) 0;
  621.                       }
  622.                     break;
  623.                   }
  624.                break;
  625.  
  626.          case E_SEND:            /* send a message */
  627.                W(esc)[TEXT_COUNT] = 0;
  628.                if (W(esc)[cnt]>0 && (W(snarf)=malloc(W(esc)[cnt]+1))
  629.                                   != (char *)0) {
  630.                   W(flags) |= W_TEXT;
  631.                   W(code) = T_SEND;
  632.                   }
  633.                break;
  634.  
  635.          case E_BITGET:            /* upload a bitmap (temporary)*/
  636.                {
  637.                int offset = W(esc)[2];
  638.                int which = *W(esc);
  639.                int size = W(esc)[1];
  640.                BITMAP *m = W(bitmaps)[which-1];
  641.  
  642.                if (cnt>1 && which>0 && which < MAXBITMAPS &&
  643.                         m != (BITMAP *) 0 &&
  644.                         size+offset<BIT_SIZE(m))
  645.                   write(W(to_fd),BIT_DATA(m)+offset,size);
  646.                }
  647.                break;
  648.          case E_BITCRT:          /* create/destroy a bitmap */
  649.                switch(cnt) {
  650.                   case 0:
  651.                      if (W(esc)[0] && W(esc[0]<=MAXBITMAPS) &&
  652.                                   W(bitmaps)[W(esc)[0]-1] != (BITMAP *) 0) {
  653.                         bit_destroy(W(bitmaps)[W(esc)[0]-1]);
  654.                         W(bitmaps)[W(esc)[0]-1] = (BITMAP *) 0;
  655. #ifdef DEBUG
  656.                         dprintf(B)(stderr,"%s: Destroyed bitmap %d\r\n",
  657.                                   W(tty),*W(esc)-1);
  658. #endif
  659.                         }
  660.                      break;
  661.                   case 2:        /* create a new bitmap */
  662.                      if (W(esc)[0] && W(esc[0]<=MAXBITMAPS) &&
  663.                                   W(bitmaps)[W(esc)[0]-1] == (BITMAP *) 0) {
  664.                         W(bitmaps)[W(esc)[0]-1] = 
  665.                               bit_alloc(Scalex(W(esc)[1]),Scalex(W(esc)[2]),
  666.                                         NULL_DATA,DEPTH);
  667. #ifdef DEBUG
  668.                         dprintf(B)(stderr,"%s: created bitmap %d (%d,%d)\r\n",
  669.                                 W(tty),*W(esc),W(esc)[1],W(esc)[2]);
  670. #endif
  671.                         }
  672.                      break;
  673.                   }
  674.                break;
  675.  
  676.          case E_BITLOAD:          /* download a bitmap */
  677.                if (cnt >=2) {
  678.                   W(esc)[TEXT_COUNT] = 0;
  679.                   W(bitmap) = bit_alloc(W(esc[0]),W(esc[1]),NULL_DATA,DEPTH);
  680.                   if (W(bitmap) != (BITMAP *) 0) {
  681.                      W(flags) |= W_TEXT;
  682.                      W(snarf) = (char *) BIT_DATA(W(bitmap));
  683.                      }
  684.                   W(code) = T_BITMAP;
  685.                   }
  686.                break;
  687.  
  688.          case E_SHAPE:          /* reshape window, make it active */
  689.  
  690.                MOUSE_OFF(mousex,mousey);
  691.  
  692.                ACTIVE_OFF();
  693.                if (win!=active) {
  694.                   cursor_off();
  695.                   expose(win);
  696.                   }
  697.                
  698.                if (cnt >= 3)
  699.                   shape(W(esc)[cnt-3], W(esc)[cnt-2],
  700.                         W(esc)[cnt-1], W(esc)[cnt]);
  701.                else if (cnt == 1)
  702.                   shape(W(esc)[cnt-1], W(esc)[cnt],
  703.                         BIT_WIDE(W(border)),
  704.                         BIT_HIGH(W(border)));
  705.  
  706.                ACTIVE_ON();
  707.                if (!(W(flags)&W_ACTIVE && mousein(mousex,mousey,win,0)))
  708.                   MOUSE_ON(mousex,mousey);
  709.  
  710.                done++;
  711.                break;
  712.  
  713.          case E_BITBLT:         /* do a bit blit */
  714.                win_rop(win,window);
  715.                done++;
  716.                break;
  717.  
  718.          case E_CIRCLE:          /* Plot a circle (or ellipse) */
  719.                circle_plot(win,window);
  720.                break;
  721.  
  722.          case E_LINE:              /* Plot a line */
  723.                win_plot(win,window);
  724.                break;
  725.  
  726.          case E_GO:              /* Go; move graphics pointer */
  727.                win_go(win);
  728.                break;
  729.  
  730.          case E_MOVE:              /* move to x,y pixels */
  731. #ifdef CUT
  732.                   W(flags) &= ~W_SNARFABLE;
  733. #endif
  734.                   if (Do_clip())
  735.                      Set_cliphigh(W(x)+W(text).x+fsizewide,W(y)+W(text).y);
  736.           if (cnt>0) {
  737.                      W(x) = Scalex(*W(esc));
  738.                      W(y) = Scaley(W(esc)[1]);
  739.                      }
  740.                    else {
  741.                      W(x) += Scalex(*W(esc));
  742.                      }
  743.                    if (W(x)+fsizewide > WIDE && !(W(flags)&W_NOWRAP))
  744.                       W(x) = WIDE-fsizewide;
  745.                    if (W(y) > HIGH)
  746.                       W(y) = HIGH - fsizehigh;
  747.                    if (Do_clip())
  748.                       Set_cliplow(W(x)+W(text).x,W(y)+W(text).y-fsizehigh);
  749.                break;
  750.  
  751.          case E_CUP:              /* move to col,row (zero based) */
  752.                if (cnt < 1) break;
  753.                   {
  754.                   register int x = W(esc)[cnt-1] * fsizewide;
  755.                   register int y = W(esc)[cnt] * fsizehigh;
  756.                   if (x == BETWEEN(-1,x,T_WIDE-fsizewide) &&
  757.                       y == BETWEEN(-1,y,T_HIGH)) {
  758.                       if (Do_clip())
  759.                         Set_cliphigh(W(x)+W(text).x+fsizewide,W(y)+W(text).y);
  760.                       W(y) = y+fsizehigh;
  761.                       W(x) = x;
  762.                       if (Do_clip())
  763.                          Set_cliplow(W(x)+W(text).x,W(y)+W(text).y-fsizehigh);
  764.                       }
  765.                   }
  766.                break;
  767.  
  768.          case E_VI:              /* turn on vi hack */
  769.                W(flags) |= W_VI;
  770.                break;
  771.  
  772.          case E_NOVI:              /* turn off vi hack */
  773.                W(flags) &= ~W_VI;
  774.                break;
  775.  
  776.          case E_PUSH:            /* push environment */
  777.               win_push(win,*W(esc));
  778.               break;
  779.  
  780.          case E_POP:            /* pop old environment */
  781.               MOUSE_OFF(mousex,mousey);
  782.               win_pop(win);
  783.               if (!(W(flags)&W_ACTIVE && mousein(mousex,mousey,win,0)))
  784.                  MOUSE_ON(mousex,mousey);
  785.               done++;
  786.               break;
  787.  
  788.          case E_TEXTREGION:        /* setup text region */
  789.               switch (cnt) {
  790.                  case 1:    /* setup scrolling region (~aka vt100) */
  791.                       if (W(esc)[0] >=0 && W(esc)[1] >= W(esc)[0] && 
  792.                                   W(esc)[1]*fsizehigh < BIT_HIGH(W(window))) {
  793.                          W(text.x) = 0;
  794.                          W(text.wide) = BIT_WIDE(W(window));
  795.                          W(text.y) = fsizehigh*W(esc[0]);
  796.                          W(text.high) = fsizehigh*(1+W(esc[1])) - W(text.y);
  797.                          if (W(y) < W(text.y)+fsizehigh)
  798.                             W(y) = W(text.y) + fsizehigh;
  799.                          if (W(y) > W(text.high))
  800.                             W(y) = W(text.high);
  801.                          }
  802.                       break;
  803.                  case 3:        /* set up entire region */
  804.                       W(text.wide) = Scalex(W(esc[2]));
  805.                       W(text.high) = Scaley(W(esc[3]));
  806.                       W(text.x) = Scalex(W(esc[0]));
  807.                       W(text.y) = Scaley(W(esc[1]));
  808.                       if (W(text.high) >= fsizehigh*MIN_Y  &&
  809.                                        W(text.wide) >= fsizewide*MIN_X) {
  810.                          W(x) = 0;
  811.                          W(y) = fsizehigh;
  812. #ifdef CUT
  813.                          W(flags) &= ~W_SNARFABLE;
  814. #endif
  815.                          break;
  816.                          }
  817.                       W(text.x) = 0;
  818.                       W(text.y) = 0;
  819.                       W(text.wide) = 0;
  820.                       W(text.high) = 0;
  821.                       break;
  822.                  case 4:    /* set up entire region (use rows, cols) */
  823.                       W(text.x) = W(esc[0]) * fsizewide;
  824.                       W(text.y) = W(esc[1]) * fsizehigh;
  825.                       W(text.wide) = W(esc[2]) * fsizewide;
  826.                       W(text.high) = W(esc[3]) * fsizehigh;
  827.                       if (W(text.high) >= fsizehigh*MIN_Y  &&
  828.                                        W(text.wide) >= fsizewide*MIN_X) {
  829.                           W(x) = 0;
  830.                           W(y) = fsizehigh;
  831.                           break;
  832.                           }
  833.                       break;
  834.                  case 0:         /* clear text region */
  835. #ifdef CUT
  836.                       if (W(text.x)%fsizewide!= 0 || W(text.y)%fsizehigh!=0)
  837.                          W(flags) &= ~W_SNARFABLE;
  838. #endif
  839.                       W(text.x) = 0;
  840.                       W(text.y) = 0;
  841.                       W(text.wide) = 0;
  842.                       W(text.high) = 0;
  843.                       break;
  844.                  }
  845.               done++;
  846.               break;
  847.  
  848.          case E_SETMODE:          /* set a window mode */
  849. #ifdef DEBUG
  850.               dprintf(E)(stderr,"%s: setting mode %d\r\n",W(tty),*W(esc));
  851. #endif
  852.               switch(W(esc)[0]) {
  853.          case M_STANDOUT:
  854.               standout(win);
  855.               break;
  856.                  case M_BACKGROUND:    /* enable background writes */
  857.                       W(flags) |= W_BACKGROUND;
  858.                       break;
  859.                  case M_NOINPUT:    /* disable keyboard input */
  860.                       W(flags) |= W_NOINPUT;
  861.                       break;
  862.                  case M_AUTOEXPOSE:    /* auto expose upon write */
  863.                       W(flags) |= W_EXPOSE;
  864.                       break;
  865.                  case M_WOB:        /* set white on black */
  866.                       if (W(flags)&W_REVERSE) 
  867.                          break;
  868. #ifdef COLOR
  869.                       W(style) = W(style)&NOCOLOR |
  870.                             (~W(style))&~NOCOLOR;
  871.                       W(background) = W(background)&NOCOLOR |
  872.                             (~W(background))&~NOCOLOR;
  873.                       CLEAR(window,W(background));
  874.                       BORDER(win);
  875. #else
  876.                       W(background) = BIT_SET;
  877.                       W(flags)|= W_REVERSE;
  878.                       if (W(flags)&W_OVER)
  879.                          W(style) = ROP_INVERT(W(style));
  880.                       else
  881.                          W(style)= W(flags)&W_STANDOUT ?
  882.                                           BIT_SRC : BIT_NOT(BIT_SRC);
  883.                       CLEAR(window,BIT_NOT(BIT_DST));
  884. #endif
  885.                       if (Do_clip())
  886.                          Set_all();
  887.                       break;
  888.                  case M_NOWRAP:      /* turn on no-wrap */
  889.                       W(flags) |= W_NOWRAP;
  890.                       break;
  891.                  case M_OVERSTRIKE:    /* turn on overstrike */
  892.                       W(style) = W(style)&~NOCOLOR | W(op)&NOCOLOR;
  893.                       W(flags) |= W_OVER;
  894.                       break;
  895.                  case M_ABS:        /* set absolute coordinate mode */
  896.                       W(flags) |= W_ABSCOORDS;
  897.                       break;
  898.                  case M_DUPKEY:        /* duplicate esc char from keyboard */
  899.                       W(flags) |= W_DUPKEY;;
  900.                       if (cnt > 0)
  901.                          W(dup) = W(esc[1])&0xff;
  902.                       else
  903.                          W(dup) = DUP_CHAR;
  904.                       break;
  905.                  case M_NOBUCKEY:    /* set no buckey interpretation mode */
  906.                       W(flags) |= W_NOBUCKEY;
  907.                       break;
  908. #ifndef NOSTACK
  909.                  case M_STACK:        /* enable event stacking */
  910.                       EVENT_SET_MASK(win,EVENT_STACK);
  911.                       break;
  912. #endif
  913.  
  914. #ifdef CUT
  915.                  case M_SNARFLINES:    /* only cut lines */
  916.                       W(flags) |= W_SNARFLINES;
  917.                       break;
  918.                  case M_SNARFTABS:    /* change spaces to tabs */
  919.                       W(flags) |= W_SNARFTABS;
  920.                       break;
  921.                  case M_SNARFHARD:    /* snarf even if errors */
  922.                       W(flags) |= W_SNARFHARD;
  923.                       break;
  924. #endif
  925.                  case M_ACTIVATE:    /* activate the window */
  926.                       if (win == active) 
  927.                           break;
  928.                       
  929.                       MOUSE_OFF(mousex,mousey);
  930.  
  931.                       cursor_off();
  932.                       ACTIVE_OFF();
  933.                       expose(win);
  934.                       ACTIVE_ON();
  935.                       cursor_on();
  936.                       done++;
  937.  
  938.                       if (!(W(flags)&W_ACTIVE && mousein(mousex,mousey,win,0)))
  939.                          MOUSE_ON(mousex,mousey);
  940.                       break;
  941.                       }
  942.               break;
  943.  
  944.          case E_CLEARMODE:          /* clear a window mode  */
  945. #ifdef DEBUG
  946.               dprintf(E)(stderr,"%s: clearing mode %d\r\n",W(tty),*W(esc));
  947. #endif
  948.               switch(W(esc)[0]) {
  949.          case M_STANDOUT:
  950.               standend(win);
  951.               break;
  952.                  case M_BACKGROUND:    /* don't permit background writes */
  953.                       W(flags) &= ~W_BACKGROUND;
  954.                       break;
  955.                  case M_NOINPUT:    /* permit keyboard input */
  956.                       W(flags) &= ~W_NOINPUT;
  957.                       break;
  958.                  case M_AUTOEXPOSE:    /* don't auto expose */
  959.                       W(flags) &= ~W_EXPOSE;
  960.                       break;
  961.                  case M_WOB:        /* set black-on-white */
  962.                       if (!(W(flags)&W_REVERSE)) 
  963.                          break;
  964. #ifdef COLOR
  965.                       W(style) = W(style)&NOCOLOR |
  966.                             (~W(style))&~NOCOLOR;
  967.                       W(background) = W(background)&NOCOLOR |
  968.                             (~W(background))&~NOCOLOR;
  969.                       CLEAR(window,W(background));
  970.                       BORDER(win);
  971. #else
  972.                       W(background) = BIT_CLR;
  973.                       W(flags)&= ~W_REVERSE;
  974.                       if(W(flags)&W_OVER)
  975.                          W(style) = ROP_INVERT(W(style));
  976.                       else
  977.                          W(style)= W(flags)&W_STANDOUT ?
  978.                                 BIT_NOT(BIT_SRC) : BIT_SRC;
  979.                       CLEAR(window,BIT_NOT(BIT_DST));
  980. #endif
  981.                       if (Do_clip())
  982.                          Set_all();
  983.                       break;
  984.                  case M_NOWRAP:      /* turn off no-wrap */
  985.                       W(flags) &= ~W_NOWRAP;
  986.                       break;
  987.                  case M_OVERSTRIKE:    /* turn off overstrike */
  988.                       if ( !(W(flags)&W_STANDOUT) ^ !(W(flags)&W_REVERSE))
  989. #ifdef COLOR
  990.                          W(style) = BIT_SRC | ~NOCOLOR & W(background);
  991.                       else
  992.                          W(style) = BIT_SRC | ~NOCOLOR & W(style);
  993. #else
  994.                          W(style) = BIT_NOT(BIT_SRC);
  995.                       else
  996.                          W(style) = BIT_SRC;
  997. #endif
  998.                       W(flags) &= ~W_OVER;
  999.                       break;
  1000.                  case M_ABS:        /* set relative coordinate mode */
  1001.                       W(flags) &= ~W_ABSCOORDS;
  1002.                       break;
  1003.                  case M_DUPKEY:        /* reset keyboard dup-ky mode */
  1004.                       W(flags) &= ~W_DUPKEY;
  1005.                       break;
  1006.                  case M_NOBUCKEY:    /* reset no buckey interpretation mode
  1007.                     */
  1008.                       W(flags) &= ~W_NOBUCKEY;
  1009.                       break;
  1010. #ifndef NOSTACK
  1011.                  case M_STACK:        /* enable event stacking */
  1012.                       EVENT_CLEAR_MASK(win,EVENT_STACK);
  1013.                       break;
  1014. #endif
  1015. #ifdef CUT
  1016.                  case M_SNARFLINES:    /* only cut lines */
  1017.                       W(flags) &= ~W_SNARFLINES;
  1018.                       break;
  1019.                  case M_SNARFTABS:    /* change spaces to tabs */
  1020.                       W(flags) &= ~W_SNARFTABS;
  1021.                       break;
  1022.                  case M_SNARFHARD:    /* snarf even if errors */
  1023.                       W(flags) &= ~W_SNARFHARD;
  1024.                       break;
  1025. #endif
  1026.                  case M_ACTIVATE:    /* hide the window */
  1027.                       if (!(W(flags)&W_ACTIVE) || next_window==1)
  1028.                           break;
  1029.                       MOUSE_OFF(mousex,mousey);
  1030.                       if (win!=active)
  1031.                          cursor_off();
  1032.                       ACTIVE_OFF();
  1033.                       hide(win);
  1034.                       ACTIVE_ON();
  1035.                       if (win!=active)
  1036.                          cursor_on();
  1037.                       if (!(W(flags)&W_ACTIVE && mousein(mousex,mousey,win,0)))
  1038.                          MOUSE_ON(mousex,mousey);
  1039.  
  1040.                       done++;
  1041.                       break;
  1042.                       }
  1043.               break;
  1044.  
  1045.          case E_GETINFO:          /* send window info back to shell */
  1046.               get_info(win,window,text);
  1047.               break;
  1048.                     
  1049.          case E_MAKEWIN:        /* make or goto a new window */
  1050.               MOUSE_OFF(mousex,mousey);
  1051.               win_make(win,indx);
  1052.               done++;
  1053.               break;
  1054.  
  1055.          case E_HALFWIN:        /* make a 1/2 window */
  1056.               {
  1057.               register int *p = W(esc);
  1058.               char *tty = NULL;
  1059.               char *half_window();
  1060.  
  1061.               if (cnt < 3 ||  cnt > 4)
  1062.                  break;
  1063.               MOUSE_OFF(mousex,mousey);
  1064.               if (win!=active)
  1065.                  cursor_off();
  1066.               ACTIVE_OFF();
  1067.  
  1068.               switch (cnt) {
  1069.                  case 4:
  1070.                     tty = half_window(p[0],p[1],p[2],p[3],p[4]);
  1071.                     break; 
  1072.                  case 3:
  1073.                     tty = half_window(p[0],p[1],p[2],p[3],-1);
  1074.                     break; 
  1075.                  }
  1076.               if (win!=active)
  1077.                  cursor_on();
  1078.               if (W(flags)&W_DUPKEY)
  1079.                  sprintf(buff,"%c %s\n",W(dup),tty?tty:"");
  1080.               else
  1081.                  sprintf(buff,"%s\n",tty?tty:"");
  1082.               if (tty) {
  1083.                  ACTIVE_ON();
  1084.                  }
  1085.               write(W(to_fd),buff,strlen(buff));
  1086.  
  1087.               done++;
  1088.               }
  1089.               break;
  1090.          case E_CURSOR:            /* set the mouse cursor */
  1091.               {
  1092.               BITMAP *map = W(bitmaps[*W(esc)]);
  1093.               int x0=0,y0=0;
  1094.  
  1095.               if (cnt > 0)
  1096.                  x0 = W(esc[1]);
  1097.               if (cnt > 0)
  1098.                  y0 = W(esc[2]);
  1099.  
  1100.               if (W(cursor)) {
  1101.                  bit_destroy(W(cursor));
  1102.                  W(cursor) = BIT_NULL;
  1103.                  SETMOUSEICON(&mouse_arrow);
  1104.                  }
  1105.  
  1106.               if ( cursor_ok(map,x0,y0) && (W(cursor) = 
  1107.                             bit_alloc(16,32,0,1)))
  1108.                  bit_blit(W(cursor),0,0,16,32,BIT_SRC,map,x0,y0);
  1109.               else
  1110.                  W(cursor) = BIT_NULL;
  1111.               }
  1112.               break;
  1113.  
  1114.          default:            /* not implemented */
  1115.                     break;
  1116.          }
  1117.       if (!(W(flags)&W_ESCAPE))
  1118.          W(flags) &= ~W_MINUS;
  1119.       break;
  1120.  
  1121.    /****************************************************************************
  1122.     *    Normal characters
  1123.     */
  1124.  
  1125.    default:
  1126.       switch(c&=0177) {
  1127.          case ESC :             /* turn on escape mode */
  1128.                     W(flags) |= W_ESCAPE;
  1129.                     W(flags) &= ~(W_MINUS);
  1130.                     W(esc_cnt) = 0;
  1131.                     W(esc[0]) = 0;
  1132.                     break;
  1133.  
  1134.          case C_NULL:            /* null character -- ignore */
  1135.                     break;
  1136.  
  1137.          case C_BS:            /* back space */
  1138.                     if (Do_clip()) {
  1139.                        Set_cliphigh(W(x)+W(text).x + fsizewide,0);
  1140.                        }
  1141.                     W(x) -= fsizewide;
  1142.                     if (W(x) < 0)
  1143.                        W(x) = 0;
  1144.                     if (Do_clip()) {
  1145.                        Set_cliplow(W(x)+W(text).x,10000);
  1146.                        }
  1147.                     break;
  1148.  
  1149.          case C_FF:            /* form feed */
  1150.                     CLEAR(text,W(background));
  1151.                     W(x)=0;
  1152.                     W(y)=fsizehigh;
  1153. #ifdef CUT
  1154.                     W(flags) |= W_SNARFABLE;
  1155. #endif
  1156.                     if (Do_clip())
  1157.                        Set_all();
  1158.                     done++;
  1159.                     break;
  1160.  
  1161.          case C_BELL:            /* ring the bell  */
  1162.                     bell_on();
  1163.                     if (!bell++) {
  1164.                        CLEAR(W(window),BIT_NOT(BIT_DST));
  1165.                        CLEAR(W(window),BIT_NOT(BIT_DST));
  1166.                        }
  1167.                     break;
  1168.  
  1169.          case C_TAB:            /* tab */
  1170.                     W(x) = ((W(x)/fsizewide +8)& ~ 7) * fsizewide;
  1171.                     if (W(x)+fsizewide >= T_WIDE) {
  1172.                        W(x)=0;
  1173.                        if (W(y)+fsizehigh > T_HIGH) {
  1174.                           scroll(win,text,0,T_HIGH,fsizehigh,W(background));
  1175.                           done++;
  1176.                           }
  1177.                        else
  1178.                           W(y) += fsizehigh;
  1179.                        }
  1180.                     break;
  1181.  
  1182.          case C_RETURN:            /* return */
  1183.                     if (Do_clip()) {
  1184.                        Set_cliphigh(W(x)+W(text).x + fsizewide,0);
  1185.                        Set_cliplow(W(text).x,10000);
  1186.                        }
  1187.                     W(x)=0;
  1188.                     break;
  1189.  
  1190.          case C_NL:             /* line feed */
  1191.                     if (W(y)+fsizehigh > T_HIGH) {
  1192.                        scroll(win,text,0,T_HIGH,fsizehigh,W(background));
  1193.                        done++;
  1194.                        }
  1195.                     else
  1196.                        W(y) += fsizehigh;
  1197.                     break;
  1198.          default:            /* print a character */
  1199. /*
  1200.                     while (W(y) > T_HIGH) {
  1201.                        W(y) -= fsizehigh;
  1202.                        scroll(win,text,0,T_HIGH,fsizehigh,W(background));
  1203.                        done++;
  1204.                        }
  1205. */
  1206.                     PUT_CHAR(text,W(x),W(y),W(font),W(style),c);
  1207.  
  1208.                     W(x) += fsizewide;
  1209.                     if (W(x)+fsizewide > T_WIDE && !(W(flags)&W_NOWRAP)) {
  1210.                        if (Do_clip()) {
  1211.                           Set_cliphigh(W(x)+W(text).x + fsizewide,0);
  1212.                           Set_cliplow(W(text).x,10000);
  1213.                           }
  1214.                        W(x)=0;
  1215.                        W(y) += fsizehigh;
  1216.                        if (W(y) > T_HIGH) {
  1217.                           W(y) -= fsizehigh;
  1218.                           scroll(win,text,0,T_HIGH,fsizehigh,W(background));
  1219.                           done++;
  1220.                           }
  1221.                        }
  1222.                     break;
  1223.          }
  1224.       break;
  1225.       }
  1226.  
  1227.    if (Do_clip())
  1228.       Set_cliphigh(W(x)+W(text).x+fsizewide,W(y)+W(text).y);
  1229.  
  1230.    cursor_on();
  1231.  
  1232.    MOUSE_ON(mousex,mousey);
  1233.  
  1234.    if (text != window)        /* this is probably wrong */
  1235.       bit_destroy(text);
  1236.    if (sub_window) {
  1237.       bit_destroy(window);
  1238.       }
  1239.  
  1240.    if (W(flags)&W_BACKGROUND && !(W(flags)&W_ACTIVE))
  1241.       update(win, &clip);
  1242.    return(indx);
  1243.    }
  1244.  
  1245.  
  1246. static
  1247. standout( win )
  1248. register WINDOW *win;
  1249. {
  1250.     int    cnt;
  1251.  
  1252.     if (W(flags)&W_STANDOUT)
  1253.         return;
  1254. #ifdef COLOR
  1255.     cnt = W(style);
  1256.     W(style) = W(background);
  1257.     W(background) = cnt;
  1258. #else
  1259.  
  1260.     if (W(flags)&W_OVER) 
  1261.         W(style) = ROP_INVERT(W(style));
  1262.     else
  1263.         W(style) = W(flags)&W_REVERSE ? BIT_SRC : BIT_NOT(BIT_SRC);
  1264. #endif
  1265.     W(flags) |= W_STANDOUT;
  1266. }
  1267.  
  1268.  
  1269. static
  1270. standend( win )
  1271. register WINDOW *win;
  1272. {
  1273.     int    cnt;
  1274.  
  1275.     if (!(W(flags)&W_STANDOUT))
  1276.         return;
  1277. #ifdef COLOR
  1278.     cnt = W(style);
  1279.     W(style) = W(background);
  1280.     W(background) = cnt;
  1281. #else
  1282.  
  1283.     if (W(flags)&W_OVER) 
  1284.         W(style) = ROP_INVERT(W(style));
  1285.     else
  1286.         W(style) = W(flags)&W_REVERSE ? BIT_NOT(BIT_SRC) : BIT_SRC;
  1287. #endif
  1288.     W(flags) &= ~ W_STANDOUT;
  1289. }
  1290.